<?php
/**
 * This file provides {@link PEAR2_Loader_PEAR2Svn}
 *
 * @package PEAR2_Loader
 * @version Release: @@VERSION@@
 * @copyright 2008, Joshua Eichorn
 * @license http://www.gnu.org/licenses/lgpl.html LGPL
 */

/**
 * PEAR2_Loader_Svn providing automatic support for files in a PEAR2 Svn layout
 * This follows the same pattern as PEAR2_Loader but doesn't extend it because
 * static + extension == no worky
 *
 * You can checkout http://svn.pear.php.net/PEAR2/all to get a layout that will work
 *
 * IMPORTANT NOTE this class doesn't try to be fast its not meant for production
 *
 * @package PEAR2_Loader
 * @version Release: @@VERSION@@
 * @copyright 2008, Joshua Eichorn
 * @license http://www.gnu.org/licenses/lgpl.html LGPL
 */
class PEAR2_Loader_PEAR2Svn {

    private $pear2;
    private $sandbox;
    private static $_instance = null;
    private $_filename = '';
    private $pear2Packages = array();
    private $sandboxPackages = array();

    /**
     * Automatically finds the location of the PEAR2 code and the PEAR2 sandbox
     * based on the current location of the loader file
     */
    public function __construct() {
        // assumes were in the sandbox
        $this->sandbox = realpath(dirname(__FILE__)."/../../../../"); 
        $this->pear2 = dirname($this->sandbox);

        $this->pear2Packages = $this->_dirList($this->pear2);
        $this->sandboxPackages = $this->_dirList($this->sandbox);
    }

    public static function autoload($class_name) {
        PEAR2_Loader_PEAR2Svn::getInstance()->loadClassWithoutCheck($class_name);
    }

    public function loadClassWithoutCheck($class_name)
    {
        if (!preg_match("/^PEAR2/",$class_name)) {
            return false;
        }
        $this->_filename = str_replace('_', DIRECTORY_SEPARATOR, 
            str_replace('PEAR2_','',$class_name)) . '.php';

        // find the package
        $_package = false;
        foreach($this->pear2Packages as $_p) {
            if (preg_match("/^PEAR2_$_p/",$class_name)) {
                $_package = $_p;
                break;
            }
        }
        if ($_package) {
            $this->_filename = $this->pear2.DIRECTORY_SEPARATOR.$_package.
                DIRECTORY_SEPARATOR.'src'.DIRECTORY_SEPARATOR.$this->_filename;

            unset($_p);
            unset($_package);
            unset($class_name);
            include_once $this->_filename;
        } else {
            foreach ($this->sandboxPackages as $_p) {
                if (preg_match("/^PEAR2_$_p/",$class_name)) {
                    $_package = $_p;
                    break;
                }
            }
            if ($_package) {
                $this->_filename = $this->sandbox.DIRECTORY_SEPARATOR.$_package.
                    DIRECTORY_SEPARATOR.'src'.DIRECTORY_SEPARATOR.$this->_filename;

                unset($_p);
                unset($_package);
                include_once $this->_filename;
            }
        }
    }

    /**
     * Returns a Singleton copy of this object
     *
     * Note that getInstance() assumes you will be using the include_path to search for classes.
     *
     * @return PEAR2_Loader_PEAR2Svn
     */
    public static function getInstance()
    {
        if (!isset(self::$_instance)) {
            self::$_instance = new self();
        }
        
        return self::$_instance;
    }

    private function _dirList($dir) {
        $dit = new DirectoryIterator($dir);
        $ret = array();
        foreach($dit as $d) {
            if($d->isDir() && !$d->isDot()) {
                $ret[] = basename($d);
            }
        }
        uasort($ret,array($this,'sizeCmp'));
        return $ret;
    }

    protected function sizeCmp($a,$b) {
        $as = substr_count($a,'_');
        $bs = substr_count($b,'_');
        if ($as  == $bs) {
            return 0;
        }
        elseif ($as > $bs) {
            return -1;
        }
        else {
            return 1;
        }
    }
}

/**
 *  * Register with autoload stack
 *   * @ignore
 *    */
spl_autoload_register(array(
	'PEAR2_Loader_PEAR2svn',
	'autoload'
));
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
